#ifndef VARLIST_H
#define VARLIST_H

#include <vector>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;
union VarUType{
	unsigned char uint8;
	unsigned short uint16;
	unsigned int uint32;
	unsigned long uint64;
	char int8;
	short int16;
	int int32;
	long int64;
	float float32;
};
struct VarType
{
	string name;
	int type;
	vector<VarUType> val;
};
class VarList
{
	public:
	VarList() 
	{
		constant_identifier = 0;
	};

	~VarList() {};

	string addconstant(int ctype, float start, float step, float end)
	{
		std::stringstream ss;
		ss << "c_" << constant_identifier;
		string name = ss.str();
		constant_identifier++;
		

		if(add(ss.str(), ctype, start, step, end))
			return "";

		return ss.str();
	}

	bool add(string cname, int ctype, float start, float step, float end)
	{

		VarType tmpx;
		tmpx.name = cname;
		tmpx.type = ctype;
		//cout << "Creating an " << ctype << endl;

		if(tmpx.type == 0)
		{		
			for(float i = start; i <= end; i+=step)
			{
				VarUType tmp;
				tmp.uint8 = (unsigned char)i;
				tmpx.val.push_back(tmp);
			}		
		}	
		else if(tmpx.type == 1)
		{		
			for(float i = start; i <= end; i+=step)
			{
				VarUType tmp;
				tmp.uint16 = (unsigned short)i;
				tmpx.val.push_back(tmp);
			}		
		}
		else if(tmpx.type == 2)
		{		
			for(float i = start; i <= end; i+=step)
			{
				VarUType tmp;
				tmp.uint32 = (unsigned int)i;
				tmpx.val.push_back(tmp);
			}		
		}
		else if(tmpx.type == 3)
		{		
			for(float i = start; i <= end; i+=step)
			{
				VarUType tmp;
				tmp.uint64 = (unsigned long)i;
				tmpx.val.push_back(tmp);
			}		
		}
		else if(tmpx.type == 4)
		{		
			for(float i = start; i <= end; i+=step)
			{
				VarUType tmp;
				tmp.int8 = (char)i;
				tmpx.val.push_back(tmp);
			}		
		}
		else if(tmpx.type == 5)
		{		
			for(float i = start; i <= end; i+=step)
			{
				VarUType tmp;
				tmp.int16 = (short)i;
				tmpx.val.push_back(tmp);
			}		
		}
		else if(tmpx.type == 6)
		{		
			for(float i = start; i <= end; i+=step)
			{
				VarUType tmp;
				tmp.int32 = (int)i;
				tmpx.val.push_back(tmp);
			}		
		}
		else if(tmpx.type == 7)
		{		
			for(float i = start; i <= end; i+=step)
			{
				VarUType tmp;
				tmp.int64 = (long)i;
				tmpx.val.push_back(tmp);
			}		
		}
		else if(tmpx.type == 8)
		{		
			for(float i = start; i <= end; i+=step)
			{
				VarUType tmp;
				tmp.float32 = i;
				tmpx.val.push_back(tmp);
			}		
		}

		vars.push_back(tmpx);

		return 0;
	}
	bool add(string name, int type, vector<VarUType> vals)
	{	
		for(int i = 0; i < vars.size(); i++)
			if(vars[i].name == name)
				return 1;	//variable exists
		VarType tmp;
		tmp.name = name;
		tmp.type = type;
		tmp.val = vals;
		vars.push_back(tmp);
		return 0; //no error
	};	
	bool add(string name, int type)
	{	
		for(int i = 0; i < vars.size(); i++)
			if(vars[i].name == name)
				return 1;	//variable exists
		VarType tmp;
		tmp.name = name;
		tmp.type = type;
		vars.push_back(tmp);
		return 0; //no error
	};

	bool addstring(string cname, string a)
	{
		for(int i = 0; i < vars.size(); i++)
			if(vars[i].name == cname)
				return 1;	//variable exists

		VarType tmp;
		tmp.name = cname;
		tmp.type = 0;

		for(int i = 1; i < a.length()-1; i++)
		{
			VarUType t;
			t.uint8 = a[i];
			tmp.val.push_back(t);
		}

		vars.push_back(tmp);	
		return 0;
	};

	bool addtmp(string cname, int ctype)
	{
		for(int i = 0; i < vars.size(); i++)
			if(vars[i].name == cname)
				return 1;	//variable exists
		VarType tmp;
		tmp.name = cname;
		tmp.type = ctype;
		tmp.val = var_tmp;
		vars.push_back(tmp);
		var_tmp.clear();	
		return 0;
	};

	bool add2tmp(int ctype, float a)
	{

		if(ctype == 0)
		{		

				VarUType tmp;
				tmp.uint8 = (unsigned char)a;
				var_tmp.push_back(tmp);
	
		}	
		else if(ctype == 1)
		{		

				VarUType tmp;
				tmp.uint16 = (unsigned short)a;
				var_tmp.push_back(tmp);
	
		}
		else if(ctype == 2)
		{		

				VarUType tmp;
				tmp.uint32 = (unsigned int)a;
				var_tmp.push_back(tmp);
		
		}
		else if(ctype == 3)
		{		

				VarUType tmp;
				tmp.uint64 = (unsigned long)a;
				var_tmp.push_back(tmp);
	
		}
		else if(ctype == 4)
		{		

				VarUType tmp;
				tmp.int8 = (char)a;
				var_tmp.push_back(tmp);
	
		}
		else if(ctype == 5)
		{		

				VarUType tmp;
				tmp.int16 = (short)a;
				var_tmp.push_back(tmp);

		}
		else if(ctype == 6)
		{		

				VarUType tmp;
				tmp.int32 = (int)a;
				var_tmp.push_back(tmp);
	
		}
		else if(ctype == 7)
		{		

				VarUType tmp;
				tmp.int64 = (long)a;
				var_tmp.push_back(tmp);

		}
		else if(ctype == 8)
		{		

				VarUType tmp;
				tmp.float32 = a;
				var_tmp.push_back(tmp);
		
		}

		return 0;
	};
	int change(string name, vector<VarUType> &var)
	{
		for(int i = 0; i < vars.size(); i++)
		{
			if(vars[i].name == name)
			{
				vars[i].val = var;
				return 0;	//no error	
			}
		}

		return 1; //cannot found
	}
	int remove(string name)
	{
		for(int i = 0; i < vars.size(); i++)
		{
			if(vars[i].name == name)
			{

				vars.erase(vars.begin() + i);

				return 0;	//no error	
			}
		}

		return 1; //cannot found		
	}
	void print(int i)
	{
		if(vars[i].type == 0)
		{
			cout << i << "\t" << vars[i].name << "\t" << vars[i].type << "\t[ ";
			for(int j = 0; j < vars[i].val.size();j++)
				cout << vars[i].val[j].uint8 << " ";
			cout << "]" << endl;
		}
		else if(vars[i].type == 1)
		{
			cout << i << "\t" << vars[i].name << "\t" << vars[i].type << "\t[ ";
			for(int j = 0; j < vars[i].val.size();j++)
				cout << vars[i].val[j].uint16 << " ";
			cout << "]" << endl;
		}			
		else if(vars[i].type == 2)
		{
			cout << i << "\t" << vars[i].name << "\t" << vars[i].type << "\t[ ";
			for(int j = 0; j < vars[i].val.size();j++)
				cout << vars[i].val[j].uint32 << " ";
			cout << "]" << endl;
		}
		else if(vars[i].type == 3)
		{
			cout << i << "\t" << vars[i].name << "\t" << vars[i].type << "\t[ ";
			for(int j = 0; j < vars[i].val.size();j++)
				cout << vars[i].val[j].uint64 << " ";
			cout << "]" << endl;
		}
		else if(vars[i].type == 4)
		{
			cout << i << "\t" << vars[i].name << "\t" << vars[i].type << "\t[ ";
			for(int j = 0; j < vars[i].val.size();j++)
				cout << vars[i].val[j].int8 << " ";
			cout << "]" << endl;
		}
		else if(vars[i].type == 5)
		{
			cout << i << "\t" << vars[i].name << "\t" << vars[i].type << "\t[ ";
			for(int j = 0; j < vars[i].val.size();j++)
				cout << vars[i].val[j].int16 << " ";
			cout << "]" << endl;
		}			
		else if(vars[i].type == 6)
		{
			cout << i << "\t" << vars[i].name << "\t" << vars[i].type << "\t[ ";
			for(int j = 0; j < vars[i].val.size();j++)
				cout << vars[i].val[j].int32 << " ";
			cout << "]" << endl;
		}
		else if(vars[i].type == 7)
		{
			cout << i << "\t" << vars[i].name << "\t" << vars[i].type << "\t[ ";
			for(int j = 0; j < vars[i].val.size();j++)
				cout << vars[i].val[j].int64 << " ";
			cout << "]" << endl;
		}
		else if(vars[i].type == 8)
		{
			cout << i << "\t" << vars[i].name << "\t" << vars[i].type << "\t[ ";
			for(int j = 0; j < vars[i].val.size();j++)
				cout << vars[i].val[j].float32 << " ";
			cout << "]" << endl;
		}
	}
	void listvars()
	{
		cout << "Variable List" << endl
		     << "------------------------------------------" << std::endl;

		for(int i = 0; i < vars.size(); i++)
		{
			print(i);
		}
		     
	}
	private:
	

	int constant_identifier;
	vector<VarUType> var_tmp;
	vector<VarType> vars;
};



#endif

